#include "SymbolTable.h"
#include "yyparse.h"

SymbolTable::SymbolTable():out("SymbolTable.out")
{
	head = NULL;
	rightPara = NULL;
	autoAddr = 0;
	staticAddr = 0;
	paraAddr = 0;
	tempAddr = 0;
	currentLevel = 0;

	//为统一链表操作，先建立一空白结点：
	head = new SYMBOL("_", 0, -1);
	if(!head) throw "为SymbolTable建立空白结点：无法分配SYMBOL";
}

SymbolTable::~SymbolTable()
{
	SYMBOL *p = head->next;
	while(p){
		head->next = p->next;
		delete p;
		p = head->next;
	}
	delete head;
}

void SymbolTable::insertVar(const std::string &varName, int dataType)
{
	SYMBOL *q, *p=head;
	//检查有无同名变量名
	while(p->next){
		if(p->next->name == varName)
			break;
		p = p->next;
	}
	
	if(p->next) {//有同名的情况
		//若同名符号是函数名：
		if(p->next->saveType == SAVE_TYPE_FUNC){
			//给出错误提示：
			errMsg <<"语法错误：变量名" << varName << "与某一函数同名"; 
			throw errMsg.rdbuf()->str();
		}
		//若同名符号的层次与当前层次相同：
		if(p->next->level == currentLevel){
			//给出错误提示：
			errMsg << "语法错误：变量名" << varName << "重定义";
			throw errMsg.rdbuf()->str();
		}
		q = new SYMBOL(varName, dataType, currentLevel);
		if(!q) throw "insertVar:申请SYMBOL空间失败";

		//插入新变量，并将同名变量下推
		q->next = p->next->next;
		p->next->next = NULL;
		q->xiaTui = p->next;
		p->next = q;

		
	}else{//无同名的情况
		q = new SYMBOL(varName, dataType, currentLevel);
		if(!q) throw "insertVar:申请SYMBOL空间失败";
		//将新申请到表项加入到链头
		q->next = head->next;
		head->next = q;
	}
	
	//为变量分配地址：
	if(q->level == 0) {
		//此时新节点处在0层，把静态地址赋给新节点:
		q->saveType = SAVE_TYPE_STATIC;
		q->offsetAddr = staticAddr;
		staticAddr += 4;
	}else{
		//若新节点不是0层，则分配自动变量空间：
		q->saveType = SAVE_TYPE_AUTO;
		q->offsetAddr = autoAddr;
		autoAddr += 4;
	}
}

void SymbolTable::insertFunc(const std::string &funcName, int retType,
						 unsigned long addr)
{
	SYMBOL *p=head;
	//检查有无同名变量名
	while(p->next){
		if(p->next->name == funcName)
			break;
		p = p->next;
	}
	if(p->next) {//有同名符号则语法错误：
		errMsg << "语法错误：函数"<<funcName<<"重定义";
		throw errMsg.rdbuf()->str();
	}
	p=new SYMBOL(funcName, retType, currentLevel);
	if(!p) throw "insertFunc:分配SYMBOL变量空间失败";
	//将新节点加入链头：
	p->next = head->next;
	head->next = p;

	//将函数入口地址赋给新节点：
	p->offsetAddr = addr;

	//设置saveType类型：
	p->saveType = SAVE_TYPE_FUNC;

	//设置参数链：
	p->nextPara = rightPara;

	//参数链指针重设为 0:
	rightPara = NULL;

	//参数地址清零：
	paraAddr = 0;
}

void SymbolTable::insertPara(const std::string &paraName, int dataType)
{
	SYMBOL *q;
	SYMBOL *p=head;
	//检查有无同名变量名
	while(p->next){
		if(p->next->name == paraName)
			break;
		p = p->next;
	}
	if(p->next){//有同名符号：
		if(p->next->saveType == SAVE_TYPE_FUNC) {
			//与一函数同名：
			errMsg << "语法错误：参数名"<<paraName<<"与某一函数同名";
			throw errMsg.rdbuf()->str();
		}
		if(p->next->level == currentLevel+1) {
			//与同一层的参数同名：
			errMsg << "语法错误：参数名"<<paraName<<"重定义";
			throw errMsg.rdbuf()->str();
		}
		q = new SYMBOL(paraName, dataType, currentLevel);
		if(!q) throw "insertPara:申请SYMBOL空间失败";

		//加入新节点，并将同名变量下推：
		q->next = p->next->next;
		p->next->next = NULL;
		q->xiaTui = p->next;
		p->next = q;

	}else{//无同名符号：
		q = new SYMBOL(paraName, dataType, currentLevel);
		if(!q) throw "insertPara:申请SYMBOL空间失败";

		//将新节点加入到链头：
		q->next = head->next;
		head->next = q;
	}
	//为形参分配地址：
	q->offsetAddr = paraAddr;
	paraAddr += 4;

	//设定形参域指针：
	q->nextPara = rightPara;
	rightPara = q;

	//设定类型：
	q->saveType = SAVE_TYPE_PARA;

	//设定层次：
	q->level += 1;
	
}

const SYMBOL * SymbolTable::searchVar(const std::string &varName)
{
//	std::ostringstream addrStr;
	SYMBOL *p=head;
	//搜索同名符号：
	while(p->next) {
		if(p->next->name == varName)
			break;
		p = p->next;
	}
	if(p->next) {//若有同名符号：
		switch(p->next->saveType) {
			case SAVE_TYPE_STATIC:
//				addrStr << "Data+" << p->next->offsetAddr;
				break;
			case SAVE_TYPE_AUTO:
//				addrStr << "Auto+" << p->next->offsetAddr;
				break;
			case SAVE_TYPE_PARA:
//				addrStr << "Stack+" << p->next->offsetAddr;
				break;
			default:
				errMsg << "语法错误："<<varName<<"有同名函数定义";
				throw errMsg.rdbuf()->str();
		}
	}else{//若无同名符号：
		errMsg << "语法错误："<<varName<<"没有定义";
		throw errMsg.rdbuf()->str();
	}
//	return addrStr.str();
	return p->next;
}

const SYMBOL * SymbolTable::searchFunc(const std::string &funcName)
{
//	std::ostringstream addrStr;
	SYMBOL *p=head;
	//搜索同名符号：
	while(p->next) {
		if(p->next->name == funcName)
			break;
		p = p->next;
	}
	if(p->next) {//若有同名符号：
		switch(p->next->saveType) {
			case SAVE_TYPE_FUNC:
//				addrStr << "Text+" << p->next->offsetAddr;
				break;
			default:
				errMsg << "语法错误："<<funcName<<"有同名符号定义";
				throw errMsg.rdbuf()->str();
		}
	}else{//若无同名符号：
		errMsg << "语法错误："<<funcName<<"没有定义";
		throw errMsg.rdbuf()->str();
	}
//	return addrStr.str();
	return p->next;
}

const std::string SymbolTable::newTemp(void)
{
	std::ostringstream addrStr;
	addrStr << "Temp+" << tempAddr;
	tempAddr += 4;
	return addrStr.str();
}

void SymbolTable::deleteTemp(void)
{
//	tempAddr = tempAddr - 4*n;
//	if(tempAddr<0)
//		throw "deleteTemp: tempAddr < 0";
	tempAddr = 0;
}

void SymbolTable::inBracket(void)
{
	currentLevel += 1;
}

void SymbolTable::outBracket(void)
{
	currentLevel -= 1;
	SYMBOL *q,*p=head;
	if(!head->next) return;
	//搜索同名符号：
	while(p->next) {
		if(p->next->level > currentLevel) { //需要删除的符号表项
			if(p->next->xiaTui) {//如果有下推表项：
				q = p->next->xiaTui;
				q->next = p->next->next;

			}else{//如果没有下推表项：
				q = p->next->next;
			}
			if(p->next->saveType == SAVE_TYPE_AUTO)
				autoAddr -= 4;
			delete p->next;
			p->next = q;
			//注意：函数名符号的属性nextPara需要清空
		}else {//无删除的符号
			p = p->next;
		}
		
	}
}

#include <iostream>
#include <iomanip>
void SymbolTable::printTable(void)
{
	SYMBOL *q, *p=head;
	out << std::setw(15) << "符号名"
		 << std::setw(15)  << "层次"
		 << std::setw(15)  << "数据类型"
		 << std::setw(15)  << "存储类型"
		 << std::setw(15)  << "偏移地址"
		// << std::setw(14)  << "参数链"
		 << std::endl;
	//遍历符号表：
	while(p->next) {
		q = p->next;
		//********************************
		out << std::setw(15) << q->name 
			<< std::setw(15) << q->level;
	       switch(q->dataType) {
		       case INT:
			       out<< std::setw(15) << "int";
			       
			       break;
		       case FLOAT:
			       out<< std::setw(15) << "float";
			       break;
		       default:
			       out<< std::setw(15) << "unknown";
	       }
		switch(q->saveType) {
			case SAVE_TYPE_STATIC:
				out<< std::setw(15) << "static";
				break;
			case SAVE_TYPE_AUTO:
				out<< std::setw(15) << "auto";
				break;
			case SAVE_TYPE_FUNC:
				out<< std::setw(15) << "func";
				break;
			case SAVE_TYPE_PARA:
				out<< std::setw(15) << "para";
				break;
			default:
				out<< std::setw(15) << "unknown";
				
	 	}		
		out << std::setw(15) << q->getStrAddr();
		/* 下面的代码不可使用，因为outBracket()中没有清空函数的nextPara项
		if(q->nextPara) {
			std::cout << std::setw(12) << q->nextPara->name;
		}else{
			;//std::cout << std::setw(12) << " ";
		}
		*/
		out << std::endl;


		//*********************************
		p = p->next;
	}

}

